package com.storm.util

import com.storm.anotation.PermitAll
import com.storm.model.RequestMappingVO
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationListener
import org.springframework.context.event.ContextRefreshedEvent
import org.springframework.core.annotation.AnnotatedElementUtils
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

class CollectPathComponent(
    var savePermitAll: ((List<RequestMappingVO>) -> Unit),
    val savePath: (List<RequestMappingVO>) -> Unit,
    val needSaveCache: (() -> Boolean)
): ApplicationListener<ContextRefreshedEvent>{

    override fun onApplicationEvent(event: ContextRefreshedEvent) {
        val context = event.applicationContext
        if (needSaveCache()) {
            cacheAuthPath(context)
        }
    }
    /**
     * 执行缓存项目中所有接口地址的操作
     */
    fun cacheAuthPath(context: ApplicationContext) {
        val rmList = ArrayList<RequestMappingVO>()
        val permitList = ArrayList<RequestMappingVO>()
        //获取所有有RestController注解的对象
        val beansWithAnnotation = context.getBeansWithAnnotation(RestController::class.java)
        beansWithAnnotation.values.forEach { bean ->
            val classRequestMapping =
                AnnotatedElementUtils.findMergedAnnotation(bean::class.java, RequestMapping::class.java)
            val classPath = classRequestMapping?.path?.let {
                if (it.isEmpty()) "" else it[0]
            } ?: ""
            bean::class.java.methods.forEach loop@{
                //获取RequestMapping注解
                val requestMapping = AnnotatedElementUtils.findMergedAnnotation(it, RequestMapping::class.java)
                    ?: return@loop
                val method = requestMapping.method
                val path = classPath + requestMapping.path[0]
                val name = requestMapping.name
                val permit = AnnotatedElementUtils.findMergedAnnotation(it, PermitAll::class.java)
                val requestMappingVO = RequestMappingVO(name, method.map { m -> m.name }, path)
                //是否不需要权限校验
                if (permit != null) {
                    permitList += requestMappingVO
                } else {
                    rmList += requestMappingVO
                }
            }
        }
        savePath(rmList)
        savePermitAll(permitList)
    }


}